package org.dyndns.opendemogroup.optimizer.operations;

import java.util.Random;

import org.dyndns.opendemogroup.optimizer.IOperation;
import org.dyndns.opendemogroup.optimizer.IOptimizationProblem;
import org.dyndns.opendemogroup.optimizer.Member;

/**
 * The second simplest form of crossover, based on OnePointCrossover
 */
public class LongestAlternatingSubsequenceCrossover implements IOperation
{

	public void perform ( Random randomSource, IOptimizationProblem problem,
			Member parentOne, Member parentTwo, Member childOne, Member childTwo )
	{
		final int memberSize = parentOne.getMemberSize ( );
		final int lastIndex = memberSize - 1;

		cross ( parentOne, parentTwo, childOne, memberSize, lastIndex );
		cross ( parentTwo, parentOne, childTwo, memberSize, lastIndex );

	}

	static void cross ( Member parentOne, Member parentTwo, Member child,
			final int memberSize, final int lastIndex )
	{
		int a = 0, b = 0;
		int bestA = 0, bestB = 0;
		double lastSeen = parentOne.genome[0];
		for ( int i = 1; i < memberSize; i++ )
		{
			if ( parentOne.genome[i] != lastSeen )
			{
				b = i;
			}
			else
			{
				// { record a and b as new bests if they are better!
				if ( ( b - a ) > ( bestB - bestA ) )
				{
					bestB = b;
					bestA = a;
				}
				// }
				a = i;
			}
			lastSeen = parentOne.genome[i];
		}
		// { record a and b as new bests if they are better!
		if ( ( b - a ) > ( bestB - bestA ) )
		{
			bestB = b;
			bestA = a;
		}
		// }
		if ( bestA > 0 )
		{
			child.copyFrom ( parentTwo, 0, bestA - 1 );
		}
		child.copyFrom ( parentOne, bestA, bestB );
		if ( bestB < lastIndex )
		{
			child.copyFrom ( parentTwo, bestB + 1, lastIndex );
		}
	}

}
